package org.xqh.utils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName BeanUtils
 * @Description TODO
 * @Author xuqianghui
 * @Date 2020/11/13 14:22
 * @Version 1.0
 */
@Slf4j
public class BeanUtils {

    /**
     * 获取 某一对象的 属性值, 调用 get方法.
     * @param obj
     * @param property
     * @param <T>
     * @return
     */
    public static <T> Object getObjFieldPropertyVal(T obj, String property){
        Field targetField = getClassFieldByProperty(obj, property);
        Object retVal = null;
        if(Objects.nonNull(targetField)){
            try {
                PropertyDescriptor descriptor = new PropertyDescriptor(targetField.getName(), obj.getClass());
                Method readMethod = descriptor.getReadMethod();
                retVal = readMethod.invoke(obj);
            } catch (Exception e) {
                log.error("", e);
            }
        }
        return retVal;
    }

    /**
     * 获取对象的 指定 field对象
     * @param obj
     * @param property
     * @param <T>
     * @return
     */
    public static <T> Field getClassFieldByProperty(T obj, String property){
        List<Field> fieldList = getAllFieldList(obj);
        return findByPropertyName(fieldList, property);
    }

    /**
     * 根据 属性名 获取 字段对象
     * @param fieldList
     * @param property
     * @return
     */
    public static Field findByPropertyName(List<Field> fieldList, String property){
        Field targetField = null;
        for(Field f:fieldList){
            if(Objects.equals(property, f.getName())){
                targetField = f;
            }
        }
        return targetField;
    }

    public static <T> List<Field> getAllFieldList(T obj){
        Class clz = obj.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clz != null){
            fieldList.addAll(Lists.newArrayList(clz.getDeclaredFields()));
            clz = clz.getSuperclass();
        }
        return fieldList;
    }


    /**
     * 调用对象 某一属性的set方法
     * @param obj
     * @param property
     * @param value
     * @param <T>
     */
    public static <T> void putObjFieldProperty(T obj, String property, Object value){
        Field targetField = getClassFieldByProperty(obj, property);
        putObjFieldProperty(obj, value, targetField);
    }


    /**
     * 设置value到 对象的 某个属性
     * @param obj
     * @param value
     * @param targetField
     * @param <T>
     */
    public static <T> void putObjFieldProperty(T obj, Object value, Field targetField){
        if(Objects.nonNull(targetField)){
            try {
                PropertyDescriptor descriptor = new PropertyDescriptor(targetField.getName(), obj.getClass());
                Method readMethod = descriptor.getWriteMethod();
                readMethod.invoke(obj, value);
            } catch (Exception e) {
                log.error("", e);
            }
        }
    }

    public static void main(String[] args) {
        TestClass testClass = new TestClass();
        putObjFieldProperty(testClass, "name", "namevalue");
        System.out.println(JSON.toJSONString(testClass));
    }

    @Data
    public static class TestClass{
        private String name;
        private int age;
    }
}
